package org.itest.jci.v1;

import javax.tools.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * <p>Title: JCompilerInvoker3</p>
 * <p>Date: 2019/6/20 9:51</p>
 * <p>Description: </p>
 *
 * @author sunxinhe
 */
public class JCompilerInvoker {

    public static Object invoke(String className, String method, String codes) {

        Class<?> clazz = compile(className, codes);
        try {
            // 生成对象
            Object obj = clazz.newInstance();
            Class<? extends Object> cls = obj.getClass();

            // 调用sayHello方法
            Method m = clazz.getMethod(method, String[].class);
            Object invoke = m.invoke(obj, new Object[]{new String[]{}});
            return invoke;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }


    private static Class<?> compile(String className, String javaCodes) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        StrSrcJavaObject srcObject = new StrSrcJavaObject(className, javaCodes);
        Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(srcObject);
        String flag = "-d";
        String outDir = "";
        try {
            File classPath = new File(Thread.currentThread().getContextClassLoader().getResource("").toURI());
            outDir = classPath.getAbsolutePath() + File.separator;
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }
        Iterable<String> options = Arrays.asList(flag, outDir);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, fileObjects);
        boolean result = task.call();
        if (result == true) {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    private static class StrSrcJavaObject extends SimpleJavaFileObject {
        private String content;

        StrSrcJavaObject(String name, String content) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.content = content;
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return content;
        }
    }


    public static void main(String[] args) {
        String className = "org.itest.jci.FOO";

        String method = "main";

        String codes = "package org.itest.jci;\n" +
                "\n" +
                "public class FOO {\n" +
                "\n" +
                "    public static void main(String[] args) {\n" +
                "        System.out.println(\"Test JCompilerInvoker3\");\n" +
                "    }\n" +
                "}\n";

        invoke(className, method, codes);
    }

}
